#region Namespaces

using System;
using System.Collections.Generic;
using System.Linq;

using Vibstudio.X4NET.Collections;
using Vibstudio.X4NET.Xml.XPath;

#endregion

namespace Vibstudio.X4NET.Xml.Navigation
{
    public class XmlKeyValuePairCollection : KeyValuePairCollection<XmlKeyValuePair>
    {
        #region Public Properties

        public XPathList XPaths { get; internal set; }
        
        #endregion

        #region Public Methods and Operators

        public bool ContainsKey(SearchCriterion criteria, string searchValue)
        {
            var seeker = new StringsSeeker(criteria);

            return this.Any(pair => seeker.IsExpectedString(pair.Key, searchValue));
        }

        public bool ContainsValue(SearchCriterion criteria, string searchValue)
        {
            var seeker = new StringsSeeker(criteria);

            return this.Any(pair => seeker.IsExpectedString(pair.Value, searchValue));
        }

        public XmlKeyValuePairCollection FilterByValue(SearchCriterion criteria, string searchValue)
        {
            var keyValuePairs = new XmlKeyValuePairCollection();

            var seeker = new StringsSeeker(criteria);

            keyValuePairs.AddRange(from pair in this
                                   where seeker.IsExpectedString(pair.Value, searchValue)
                                   select new XmlKeyValuePair(pair.Key, pair.Value));

            return keyValuePairs;
        }

        public List<int> GetInvalidRows(ValidationCriterion criteria, IEnumerable<string> stringsToSearch)
        {
            var invalidRows = new List<int>();

            var validator = new StringsValidator(criteria);

            int i = 0;
            foreach (string s in stringsToSearch)
            {
                i++;
                if (!validator.IsValid(s))
                {
                    invalidRows.Add(i);
                }
            }

            return invalidRows;
        }

        public IEnumerable<string> GetValues(SearchCriterion criteria, string searchValue)
        {
            var seeker = new StringsSeeker(criteria);

            return (from pair in this where seeker.IsExpectedString(pair.Value, searchValue) select pair.Value).ToList();
        }

        public string GetValue(string xpath)
        {
            if (string.IsNullOrEmpty(xpath))
            {
                throw new ArgumentNullException("xpath");
            }

            foreach (XmlKeyValuePair pair in this)
            {
                if (xpath.IsMatch(pair.XPath, StringComparison.InvariantCultureIgnoreCase))
                {
                    return pair.Value;
                }
            }

            return "";
        }

        #endregion
    }
}